package models;

import com.mysql.jdbc.Statement;
import com.sun.faces.util.CollectionsUtils.ConstMap;
import java.sql.ResultSet;
import system.Model;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import system.DbConnection;
import system.Helper;
import system.Validator;

/**
 * Class User
 * 
 * @author Rezan Achmad
 */
public class User extends Model {

    public int id;
    public String nama_lengkap;
    public String nama_panggilan;
    public String email;
    public String password;
    public String no_telepon;
    public String alamat;
    public int role_id;
    public int point;
    public int is_registered;

    public User() {
        nama_lengkap = "";
        nama_panggilan = "";
        email = "";
        password = "";
        no_telepon = "";
        alamat = "";
        role_id = 1;
        point = 0;
        is_registered = 0;
    }

    @Override
    public boolean add() {
        String sql =
                "INSERT INTO `user`(`nama_lengkap`, `nama_panggilan`, `email`, `password`, `no_telepon`, `alamat`, `is_registered`)"
                + "VALUES('" + nama_lengkap + "', '" + nama_panggilan + "', '" + email + "', '" + password + "', '" + no_telepon + "', '" + alamat + "', '" + is_registered + "')";
        Statement statement = getStatement();
        try {
            statement.execute(sql);
        } catch (SQLException ex) {
            Logger.getLogger(User.class.getName()).log(Level.SEVERE, null, ex);
            return false;
        }
        return true;
    }

    public boolean activate() {
        int register = 1;
        String sql =
                "UPDATE `user` SET `is_registered` = " + register + " "
                + "WHERE `email` = '" + email + "' ";

        try {
            getStatement().executeUpdate(sql);
            return true;
        } catch (SQLException ex) {
            Logger.getLogger(User.class.getName()).log(Level.SEVERE, null, ex);
        }

        return false;
    }

    /**
     * Melakukan autentikasi. email dan password harus terdefinisi.
     * @return Mengembalikan true jika autentikasi berhasil, false jika gagal.
     */
    public boolean authenticate() {
        // Init result
        ResultSet result = null;
        Boolean exist = false;

        // Prepare query
        String sql = "SELECT `email`, `password` FROM `user` WHERE `is_registered`='1' AND `email`='" + email + "' AND `password`='" + Helper.MD5(password) + "'";

        try {
            // Execute Query
            result = getStatement().executeQuery(sql);
            exist = result.next();
        } catch (SQLException ex) {
            Logger.getLogger(User.class.getName()).log(Level.SEVERE, null, ex);
        }

        return result != null && exist;
    }

    /**
     * Ganti Password
     * @param newPassword Password baru
     * @return Mengembalikan true jika berhasil, false jika gagal.
     */
    public boolean changePassword(String newPassword) {
        // Hash
        String hashedNewPassword = Helper.MD5(newPassword);

        // Menyiapkan Query
        String sql =
                "UPDATE `user` SET `password` = '" + hashedNewPassword + "' "
                + "WHERE `id` = '" + id + "'";

        try {
            // Eksekusi
            getStatement().executeUpdate(sql);

            // Sukses, set newPassword
            password = hashedNewPassword;
        } catch (SQLException ex) {
            Logger.getLogger(Kategori.class.getName()).log(Level.SEVERE, null, ex);
            addError("password", "Gagal mengubah password.");
            return false;
        }

        return true;
    }

    public static User getBySql(String sql) {
        try {
            ResultSet rs = DbConnection.getStatement().executeQuery(sql);

            if (rs.next()) {
                User user = new User();
                user.setAttributes(rs);
                return user;
            }
        } catch (SQLException ex) {
            Logger.getLogger(User.class.getName()).log(Level.SEVERE, null, ex);
        }

        return null;
    }

    public static User getByEmail(String email) {
        return getBySql("SELECT * FROM `user` WHERE `email`='" + email + "'");
    }

    public User get(int id) {
        String sql = "SELECT * FROM `user` WHERE `id`='" + id + "'";
        return User.getBySql(sql);
    }

    public ArrayList<Pesanan> getPesanans() {
        return Pesanan.getInstance().getAll(id);
    }
    
    /**
     * Reset Password
     * @return Mengembalikan string password baru jika berhasil, null jika gagal.
     */
    public String resetPassword() {
        String newPassword = Helper.GenerateRandomString();
        return changePassword(newPassword) ? newPassword : null;
    }

    @Override
    public void setAttributes(ResultSet rs) throws SQLException {
        id = rs.getInt("id");
        nama_lengkap = rs.getString("nama_lengkap");
        nama_panggilan = rs.getString("nama_panggilan");
        email = rs.getString("email");
        password = rs.getString("password");
        no_telepon = rs.getString("no_telepon");
        alamat = rs.getString("alamat");
        role_id = rs.getInt("role_id");
        point = rs.getInt("point");
        is_registered = rs.getInt("is_registered");
    }

    public ArrayList<User> getAllBySql(String sql) {
        try {
            // Execute Query
            ResultSet rs = DbConnection.getStatement().executeQuery(sql);

            // Check result
            if (!rs.next()) {
                return null;
            }

            // Iterate and add to list
            User user;
            ArrayList<User> listUser = new ArrayList<User>();
            do {
                user = new User();
                user.setAttributes(rs);
                listUser.add(user);
            } while (rs.next());

            return listUser;
        } catch (SQLException ex) {
            Logger.getLogger(Pesanan.class.getName()).log(Level.SEVERE, null, ex);
        }

        return null;
    }

    public ArrayList<User> getAll() {
        String sql = "SELECT * FROM `user`";
        return getAllBySql(sql);
    }
    
    public ArrayList<User> getAllPegawai() {
        String sql = ""
                + "SELECT `user`.* "
                + "FROM `user` "
                + "JOIN `role` ON `role`.`id` = `user`.`role_id` "
                + "WHERE `role`.`nama` = 'pegawai'";
        return getAllBySql(sql);
    }
    
    public String[] getAllEmailPegawai() {
        // Cari semua pegawai
        ArrayList<User> pegawais = User.getInstance().getAllPegawai();
        
        // Kumpulkan semua email pegawai
        String _email[] = new String[pegawais.size()];
        for(int i =  0; i < _email.length; ++i)
            _email[i] = pegawais.get(i).email;
        
        return _email;
    }

    public Role getRole() {
        return Role.getInstance().get(role_id);
    }

    public String getRoleName() {
        return getRole().nama;
    }

    /**
     * Update User.
     * @param validate Apakah atribute divalidasi terlebih dahulu sebelum diupdate
     * @return Mengembalikan true jika berhasil atau false jika gagal.
     */
    public boolean update(boolean validate) {
        // Validasi data
        if (validate && !validate()) {
            return false;
        }

        // Update
        String sql =
                "UPDATE `user` SET `nama_lengkap` = '" + nama_lengkap + "', "
                + "`nama_panggilan` = '" + nama_panggilan + "', "
                + "`email` = '" + email + "', "
                + "`no_telepon` = '" + no_telepon + "', "
                + "`alamat` = '" + alamat + "', "
                + "`role_id` = '" + role_id + "', "
                + "`point` = '" + point + "' "
                + "WHERE `id` = '" + id + "'";

        try {
            getStatement().executeUpdate(sql);
        } catch (SQLException ex) {
            Logger.getLogger(Kategori.class.getName()).log(Level.SEVERE, null, ex);
            addErrorGlobal("Terdapat kesalahan. Gagal mengubah data.");
            return false;
        }

        return true;
    }

    /**
     * Update User.
     * @return Mengembalikan true jika berhasil atau false jika gagal.
     */
    public boolean update() {
        return update(true);
    }

    public static boolean tukarPoin(String email) {
        User userUpdate = getByEmail(email);
        if (userUpdate.point >= 1000) {
            userUpdate.point -= 1000;
            return userUpdate.update();
        } else {
            return false;
        }
    }

    public static boolean batalTukarPoin(String email) {
        User userUpdate = getByEmail(email);
        userUpdate.point += 1000;
        return userUpdate.update();
    }
    
    public boolean batalTukarPoin(int userId) {
        User user = get(userId);
        user.point += 1000;
        return user.update();
    }

    public static User getInstance() {
        return new User();
    }

    @Override
    public boolean validate() {
        boolean valid = true;
        Validator validator = Validator.getInstance();

        valid = validator.notEmptyString(email, this, "email");
        valid = validator.notEmptyString(nama_lengkap, this, "nama_lengkap");
        valid = validator.notEmptyString(nama_panggilan, this, "nama_panggilan");
        valid = validator.notEmptyString(alamat, this, "alamat");
        valid = validator.notEmptyString(no_telepon, this, "no_telepon");

        return valid;
    }

    @Override
    public void initAttributesLabel() {
        attributesLabel = new HashMap<String, String>();
        attributesLabel.put("email", "Email");
        attributesLabel.put("nama_lengkap", "Nama Lengkap");
        attributesLabel.put("nama_panggilan", "Nama Panggilan");
        attributesLabel.put("alamat", "Alamat");
        attributesLabel.put("no_telepon", "No Telepon");
    }
}